package com.health.personal.service.impl;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.github.javafaker.Faker;
import com.health.common.core.exception.ServiceException;
import com.health.common.core.po.TuserPo;
import com.health.common.core.utils.StringUtils;
import com.health.personal.domain.dto.RegisterRetrieveDto;
import com.health.personal.domain.po.PatientProfilePo;
import com.health.personal.mapper.PatientProfileMapper;
import com.health.personal.mapper.TUserMapper;
import com.health.personal.service.TUserService;
import jakarta.mail.MessagingException;
import jakarta.mail.internet.MimeMessage;
import jakarta.servlet.http.HttpServletRequest;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.mail.javamail.MimeMessageHelper;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.concurrent.ThreadLocalRandom;
/**
 * @BelongsProject: dimensionality-manage
 * @BelongsPackage: com.health.personal.service.impl
 * @Author: 许力匀
 * @CreateTime: 2024-12-12  19:44
 * @Description: TODO
 * @Version: 1.0
 */
@Service
@Slf4j
public class TUserServiceImpl extends ServiceImpl<TUserMapper, TuserPo>  implements TUserService{

    @Autowired
    private TUserMapper tUserMapper ;

    @Autowired
    private StringRedisTemplate stringRedisTemplate ;

    @Autowired
    private JavaMailSender javaMailSender ;

    @Autowired
    private PatientProfileMapper patientProfileMapper ;

    //邮件验证码redis缓存位置
    private static final String CAPTCHA_KEY = "captcha_codes:";
    //邮件正则校验
    private static final String EMAIL_REGEX = "^[a-zA-Z0-9_+&*-]+(?:\\.[a-zA-Z0-9_+&*-]+)*@(?:[a-zA-Z0-9-]+\\.)+[a-zA-Z]{2,7}$";
    //限制时间每一分钟发一次
    private static final String TIME_ORDER = "time:order";
    //随机生成名字
    private static final Faker faker = new Faker();


    @Override
    public TuserPo selectByEmail(String email) {
        //非空校验
        if(StringUtils.isEmpty(email)){
            throw  new RuntimeException("邮件不能为空");
        }
        //正则校验
        if (!email.matches(EMAIL_REGEX)) {
            throw new RuntimeException("邮件格式不正确");
        }
        //查询所有用户
        List<TuserPo> tUsers = tUserMapper.selectList(null);
        //用stream流过滤出符合条件的数据
        return tUsers.stream().filter(tUser -> tUser.getEmail().equals(email)).findFirst().orElse(null);

    }

    @Override
    public void sendCaptcha(String email) {

        MimeMessage mimeMessage = javaMailSender.createMimeMessage();
        try {
            //校验验证码是否过期
            Boolean aBoolean = stringRedisTemplate.hasKey(TIME_ORDER+email);
            if(Boolean.TRUE.equals(aBoolean)){
                throw  new RuntimeException("一分钟只能发送一次验证码,请勿重复发送");
            }
            MimeMessageHelper helper = new MimeMessageHelper(mimeMessage, true);
            //生成四位数数字验证码
            int nextInt = ThreadLocalRandom.current().nextInt(1000, 10000);
            helper.setSubject("验证码通知");
            //验证码非空校验
            helper.setText("您的验证码是:"+String.valueOf(nextInt)+"请在一分钟内完成登录");
            helper.setFrom("3174057727@qq.com");
            helper.setTo(email);
            javaMailSender.send(mimeMessage);
            //发送成功验证码存redis
            stringRedisTemplate.opsForValue().set(CAPTCHA_KEY+email,String.valueOf(nextInt),1, java.util.concurrent.TimeUnit.MINUTES);
        } catch (MessagingException e) {
            log.error("验证码发送异常");
        }
    }

    @Override
    public void  updatePassword(String email, String password,String code,String beginPassword) {
        //校验密码
        extracted(email, password, code, beginPassword);
        //验证码校验
        extracted(email, code);
        //修改请求
        tUserMapper.updatePassword(email,password);

    }

    private static void extracted(String email, String password, String code, String beginPassword) {
        if(!password.equals(beginPassword)){
            throw  new RuntimeException("两次密码不一致");
        }
        if (!email.matches(EMAIL_REGEX)) {
            throw new RuntimeException("请输入正确的邮件格式");
        }
        if(StringUtils.isEmpty(password)){
            throw  new ServiceException("请输入密码");
        }
        if(StringUtils.isEmpty(code)){
            throw  new ServiceException("请输入验证码");
        }
        //校验密码长度
        if(password.length()<6){
            throw  new ServiceException("密码长度不能小于6位");
        }
    }

    private void  extracted(String email, String code) {
        //校验验证码
        Boolean aBoolean = stringRedisTemplate.hasKey(CAPTCHA_KEY + email);
        if(Boolean.FALSE.equals(aBoolean)){
            throw  new ServiceException("请先发送验证码");
        }
        //取出验证码
        String captcha = stringRedisTemplate.opsForValue().get(CAPTCHA_KEY + email);
        assert captcha != null:"验证码已过期，请重新发送验证码";
        //校验验证码
        if(!captcha.equals(code)){
            throw  new ServiceException("验证码不正确");
        }
    }

    @Override
    @Transactional
    public void register(RegisterRetrieveDto registerRetrieveDto) {
        //校验邮箱是否已经注册
        TuserPo user = selectByEmail(registerRetrieveDto.getEmail());
        if(user!=null){
            throw  new ServiceException("邮箱已经注册，不能重复注册哦");
        }
        //验证码校验
        extracted(registerRetrieveDto.getEmail(), registerRetrieveDto.getCode());
        //校验密码
        extracted(registerRetrieveDto.getEmail(), registerRetrieveDto.getPassword(), registerRetrieveDto.getCode(), registerRetrieveDto.getBeginPassword());
        TuserPo tuserPo = new TuserPo();
        //邀请码
        tuserPo.setInviteCode(registerRetrieveDto.getInviteCode());
        //密码
        tuserPo.setPassword(registerRetrieveDto.getPassword());
        //邮箱
        tuserPo.setEmail(registerRetrieveDto.getEmail());
        //h币
        tuserPo.setHCoin(0.0);
        //姓名
        tuserPo.setRealName(registerRetrieveDto.getRealName());
        //注册患者信息
        int register = tUserMapper.register(tuserPo);
        //添加患者信息表
        PatientProfilePo patientProfilePo = new PatientProfilePo();
        //患者外键
        patientProfilePo.setTId(tuserPo.getId());
        //昵称
        patientProfilePo.setNickname(faker.name().fullName());
        //邮箱
        patientProfilePo.setEmail(registerRetrieveDto.getEmail());
        //初始化患者个人信息
        patientProfileMapper.insert(patientProfilePo);
    }


}
